package group.rober.dataform.handler.impl;

import group.rober.dataform.model.DataForm;
import group.rober.dataform.model.DataFormElement;
import group.rober.runtime.kit.StringKit;
import group.rober.runtime.kit.ValidateKit;
import group.rober.runtime.lang.MapData;
import group.rober.sql.converter.NameConverter;
import group.rober.sql.core.MapDataAccessor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.JdbcUtils;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;

/**
 * Map类型数据处理公共部分剥离
 */
public abstract class MapDataHandler {
    protected MapDataAccessor mapDataAccessor;

    public MapDataAccessor getMapDataAccessor() {
        return mapDataAccessor;
    }

    public void setMapDataAccessor(MapDataAccessor mapDataAccessor) {
        this.mapDataAccessor = mapDataAccessor;
    }

    /**
     * 建立列和属性的映射
     * @param dataForm
     * @return
     */
    protected Map<String,String> getColumn2PropertyMap(final DataForm dataForm){
        //
        final Map<String,String> columnPropertyMap = new HashMap<String,String>();
        List<DataFormElement> elements = dataForm.getElements();
        for(DataFormElement element : elements) {
            String colName = element.getColumn();
            String propName = StringKit.nvl(element.getCode(),colName);
            columnPropertyMap.put(colName,propName);
        }
        return columnPropertyMap;
    }

    /**
     * 建立列和属性的映射(仅主键）
     * @param dataForm
     * @return
     */
    protected Map<String,String> getPkColumn2PropertyMap(final DataForm dataForm){
        final Map<String,String> columnPropertyMap = new HashMap<String,String>();
        List<DataFormElement> elements = dataForm.getElements();
        for(DataFormElement element : elements) {
            if(element.getPrimaryKey() != Boolean.TRUE)continue;
            String colName = element.getColumn();
            String propName = StringKit.nvl(element.getCode(),colName);
            columnPropertyMap.put(colName,propName);
        }
        return columnPropertyMap;
    }
    /**
     * 根据DataForm的配置，设置数据表字段和属性的映射关系
     * @param dataForm
     * @return
     */
    protected RowMapper<MapData> getDataFormRowMapper(final DataForm dataForm){
        final Map<String,String> columnPropertyMap = getColumn2PropertyMap(dataForm);

        return new RowMapper<MapData>() {
            public MapData mapRow(ResultSet rs, int rowNum) throws SQLException {
                MapData row = new MapData();

                ResultSetMetaData meta = rs.getMetaData();
                int columnCount = meta.getColumnCount();
                for(int i=1;i<=columnCount;i++){
                    String columnName = meta.getColumnName(i);
                    String propName = columnPropertyMap.get(columnName);
                    //字段在显示模板中没有指定，则忽略
                    if(StringKit.isBlank(propName))continue;
                    Object value = JdbcUtils.getResultSetValue(rs,i);
                    row.put(propName,value);
                }

                return row;
            }
        };
    }

    /**
     * 参数mapData中的KEY是属性，需要把它映射转换成数据库的字段
     * @param dataForm
     * @param object
     * @return
     */
    protected MapData getDbMapData(DataForm dataForm, MapData object){
        Map<String,String> columnPropertyMap = getColumn2PropertyMap(dataForm);
        return convertDbMapData(columnPropertyMap,object);
    }

    /**
     * 参数mapData中的KEY是属性，需要把它映射转换成数据库的字段
     * @param dataForm
     * @param dataList
     * @return
     */
    protected List<MapData> getDbMapDataList(DataForm dataForm,List<MapData> dataList){
        List<MapData> retList = new ArrayList<MapData>(dataList.size());
        for(MapData row : dataList){
            retList.add(getDbMapData(dataForm,row));
        }
        return retList;
    }

    /**
     * 根据模板设置，把主键部分抽出来
     * @param dataForm
     * @param object
     * @return
     */
    protected MapData getDbPkMapData(DataForm dataForm, MapData object){
        Map<String,String> columnPropertyMap = getPkColumn2PropertyMap(dataForm);
        return convertDbMapData(columnPropertyMap,object);
    }

    /**
     * 根据模板设置，把主键部分抽出来
     * @param dataForm
     * @param dataList
     * @return
     */
    protected List<MapData> getDbPkMapDataList(DataForm dataForm, List<MapData> dataList){
        List<MapData> retList = new ArrayList<MapData>(dataList.size());
        for(MapData row : dataList){
            retList.add(getDbPkMapData(dataForm,row));
        }
        return retList;
    }

    protected MapData convertDbMapData(Map<String,String> columnPropertyMap,MapData object){
        //KEY为数据库字段名
        MapData dbMapData = new MapData();

        Set<Map.Entry<String, String>> itemSet = columnPropertyMap.entrySet();
        for(Map.Entry<String, String> entry : itemSet){
            String column = entry.getKey();
            String prop = entry.getValue();
            Object value = object.get(prop);    //取出值
            dbMapData.put(column,value);        //把KEY换成数据列
        }

        return dbMapData;
    }

    protected NameConverter getNameConverter(final DataForm dataForm){
        return new NameConverter(){
            public String getPropertyName(String columnName) {
                return columnName;
            }
            public String getColumnName(String propertyName) {
//                DataFormElement element = dataForm.getElement(propertyName);
//                if(element==null)return propertyName;
//                return element.getColumn();
                return propertyName;
            }
            public String getClassName(String tableName) {
                return null;
            }
            public String getTableName(Class<?> clazz) {
                return null;
            }
        };
    }

    protected void validateDataForm(DataForm dataForm){
        ValidateKit.notNull(dataForm);
        String table = dataForm.getDataModel();
        String query = dataForm.getQuery();
        ValidateKit.notBlank(table,"dataform={0}.{1}的dataModel属性值为空",dataForm.getPack(),dataForm.getId());
        ValidateKit.notBlank(query,"dataform={0}.{1}的query属性值为空",dataForm.getPack(),dataForm.getId());
    }
}
